﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Xml;
using SHomeWorkshop.LunarPresentation.Expressions;

namespace SHomeWorkshop.LunarPresentation
{
    public class ModifingItem
    {
        /// <summary>
        /// 这是Operation改动的各对象的集合，——通常只有一个成员。
        /// 注意：如果是插入或删除了一个公式，则“modifiedObjects”值并不是公式所拥有的属性。
        /// “插入公式”使用“InsertExpression”，“删除公式”使用“DeleteExpression”。
        /// </summary>
        private List<Action> modifiedPropertyAndValues = new List<Action>();

        /// <summary>
        /// 根据这个列表找到对公式进行了哪些修改。
        /// </summary>
        internal List<Action> ModifiedPropertyAndValues
        {
            get { return modifiedPropertyAndValues; }
        }

        /// <summary>
        /// 只是封装了modifiedPropertyAndValues.Add()方法。
        /// </summary>
        /// <param name="action"></param>
        public void Add(Action action)
        {
            this.modifiedPropertyAndValues.Add(action);
        }

        /// <summary>
        /// 编辑器卷动位置。
        /// </summary>
        public Point EditorOffset { get; set; }

        /// <summary>
        /// 用以在“撤销”后，恢复选中某个公式。
        /// </summary>
        public string OldSelectedExID { get; set; }

        /// <summary>
        /// 用以在“重做”后，恢复选中某个公式。
        /// </summary>
        public string NewSelectedExID { get; set; }

        private string autoNumPanelID = null;

        /// <summary>
        /// 如果某个操作可能引起某个面板的自动编号发生变化，应提供此面板的ExID。
        /// </summary>
        public string AutoNumPanelID
        {
            get { return autoNumPanelID; }
            set { autoNumPanelID = value; }
        }
    }

    /// <summary>
    /// 操作的类型。
    /// </summary>
    public enum ActionType
    {
        Property, //修改属性——大部分操作都是这个类型。
        Insert, //插入公式
        Delete, //删除公式
        MoveToNext, //平移到下一个位置
        MoveToPreview,//平移到前一个位置
        Embed,
        InsertGridPanel,
        DeleteGridPanel,
        FontSizeChanging,
        DefaultExForegroundChanging,
        DefaultExBackgroundChanging,
        ExSelectionAdornerBrushChanging,
        SubPanelSelectionAdornerBrushChanging,

        DefaultHeaderText1ColorChanging,
        DefaultHeaderText2ColorChanging,
        DefaultHeaderText3ColorChanging,
        DefaultHeaderText4ColorChanging,

        AutoWrap,
        MaxTextWidth,

        //下面这些都是与“树”有关的。
        PaseteTreeLeaf,
        InsertSameLevelLeaf,
        InsertNextLevelLeaf,
        CutOrDeleteTreeLeaf,
        MoveLeafHorizontal,

        //这几个是关于页眉的操作
        PageHeaderLeft,
        PageHeaderRight,
        PageHeaderMiddle,
        TileMode,
        PageSetting,
        MaxWidthOfRootPanel,
    };

    public class Action
    {
        /// <summary>
        /// 构造存放在UndoItem的Properties列表中的各（将被更改的）属性及其值的文本表示。
        /// ——通常这个列表中只有一个属性及其值。
        /// </summary>
        /// <param name="exID">公式内部编号(Guid)。</param>
        /// <param name="exIndex">公式索引。</param>
        /// <param name="exClassName">公式类的名称。</param>
        /// <param name="name">属性名。</param>
        /// <param name="oldValue">旧属性值的文本表示方式。</param>
        /// <param name="newValue">新属性值的文本表示方式。</param>
        /// <param name="actionType">“修改操作”的类型。默认是对某个公式的某个属性进行操作。</param>
        /// <param name="parentPanelOrExID">此参数只对“插入”或“删除”Action有效。指定父面板的内部编号。
        /// ★注意：如果是“插入/删除网格子面板”则应传入网格式的内部编号。</param>
        public Action(string exID, int exIndex, string exClassName,
            string name, string oldValue, string newValue, ActionType actionType = ActionType.Property,
            string parentPanelOrExID = "")
        {
            this.exID = exID;
            this.exIndex = exIndex;
            this.exClassName = exClassName;
            this.name = name;
            this.oldValue = oldValue;
            this.newValue = newValue;
            this.actionType = actionType;
            this.parentPanelExID = parentPanelOrExID;
        }

        private string name;

        /// <summary>
        /// 更改或要撤销的属性的名称。
        /// </summary>
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        private string oldValue;

        /// <summary>
        /// 取旧属性值（以字符串形式表示）。
        /// </summary>
        public string OldValue
        {
            get { return oldValue; }
        }

        private string newValue;

        /// <summary>
        /// 取新属性值（以字符串形式表示）。
        /// </summary>
        public string NewValue
        {
            get { return newValue; }
        }

        private string exID = string.Empty;

        /// <summary>
        /// 根据这个属性找到对哪个公式作了修改。
        /// </summary>
        public string ExID
        {
            get { return exID; }
        }

        private string exClassName;

        /// <summary>
        /// 公式类名称。不应该出现抽象类。
        /// </summary>
        public string ExClassName
        {
            get { return exClassName; }
            set { exClassName = value; }
        }

        private int exIndex;

        /// <summary>
        /// 被修改的公式在其父面板中的位置索引。
        /// </summary>
        public int ExIndex
        {
            get { return exIndex; }
            set { exIndex = value; }
        }

        private ActionType actionType = ActionType.Property;

        public ActionType ActionType
        {
            get { return actionType; }
            set { actionType = value; }
        }

        private string parentPanelExID = string.Empty;

        /// <summary>
        /// 插入公式时基准位置公式的内部编号。
        /// </summary>
        public string ParentPanelOrExID
        {
            get { return parentPanelExID; }
        }
    }

    public class ModifingsList : List<ModifingItem>
    {
        /// <summary>
        /// 构造一个“可撤销项”的列表。
        /// </summary>
        /// <param name="editor">所属编辑器。</param>
        public ModifingsList(Editor parentEditor)
        {
            this.editor = parentEditor;
        }

        private Editor editor;

        public Editor Editor
        {
            get { return editor; }
        }

        //对于editor来说，如果下一步进行的操作不是Redo，则应删除多余“可撤销项目”。
        private int point = -1;

        /// <summary>
        /// 表示当前Undo到哪一步，这是个List的索引。
        /// </summary>
        public int Point
        {
            get { return point; }
        }

        private int pointOfSaving = -1;

        /// <summary>
        /// 表示执行“保存”操作时的Point。如果撤销或重做后，与此值相等，则表示
        /// 当前应显示为“已保存”。
        /// </summary>
        public int PointOfSaving
        {
            get { return pointOfSaving; }
            set { pointOfSaving = value; }
        }

        /// <summary>
        /// 执行某一项修改时，将修改信息添加到列表中。
        /// 并删除列表中在当前Point之后的所有项——这些项将不能再用于Redo。
        /// </summary>
        public void Do(ModifingItem modifingItem)
        {
            if (modifingItem != null && this.Contains(modifingItem))
            {
                MessageBox.Show("出现异常，撤销项被重复添加！",
                    Globals.appName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            if (this.point > -1)
            {
                for (int i = this.Count - 1; i > point; i--)
                {
                    this.RemoveAt(i);
                }
            }
            else
            {
                this.Clear();
            }

            if (PointOfSaving > point)
            {
                PointOfSaving = -2;
            }

            if (modifingItem != null)
            {
                this.Add(modifingItem);
                this.point++;
            }

            if (editor != null)
            {
                modifingItem.EditorOffset = new Point(editor.BaseScrolledViewer.HorizontalOffset,
                    editor.BaseScrolledViewer.VerticalOffset);

                //if (editor.SelectedExpression != null)
                //{
                //    modifingItem.NewSelectedExID = editor.SelectedExpression.ExID;
                //}
            }
        }

        /// <summary>
        /// 能否重做。
        /// </summary>
        public bool CanRedo
        {
            get
            {
                if (Point < -1 || Point > this.Count - 2)//减2，是因为Redo运算时会先加1。最大索引值只能是Count-1。
                {
                    return false;
                }

                if (this.Count <= 0) return false;
                return true;
            }
        }

        /// <summary>
        /// 将Point后移一位，并将目标公式的状态（相关属性值）刷新为新位置（Point）记录的NewValue。
        /// </summary>
        public void Redo()
        {
            if (CanRedo == false) return;

            //注意：此处与Undo不同，得先加。
            point++;

            ModifingItem mi = this[point] as ModifingItem;

            int deletedExpression = 0;

            foreach (Action action in mi.ModifiedPropertyAndValues)
            {
                switch (action.ActionType)
                {
                    case ActionType.Property:
                        {
                            Expressions.Expression ex = editor.GetExpressionByExID(editor.RootPanel, action.ExID);
                            if (ex != null)
                            {
                                ex.Redo(action);

                                //顶级标题的字号变化会影响自动编号。故应刷新自动编号。
                                if (action.Name == "FontSizeLevel" && ex.ParentPanel != null)
                                {
                                    ex.ParentPanel.RefreshAutoNumbersOfBaseText();
                                }
                            }
                            else
                            {
                                deletedExpression++;
                            }

                            break;
                        }
                    case ActionType.Insert:
                        {
                            Expressions.Expression exPanel = editor.GetExpressionByExID(editor.RootPanel, action.ParentPanelOrExID);
                            if (exPanel == null || (exPanel is Expressions.Expression == false)) return;

                            Expressions.SubPanel subPanel = exPanel as Expressions.SubPanel;

                            if (action.ExIndex >= subPanel.BasePanel.Children.Count)
                            {
                                //公式被撤销前在最后一个位置。
                                Expressions.Expression ex = subPanel.BasePanel.Children[subPanel.BasePanel.Children.Count - 1] as Expressions.Expression;
                                if (ex != null)
                                {
                                    Expressions.Expression restordExpression =
                                        Commands.Command.InsertExpressionByXmlString(false,
                                        action.NewValue, ex);
                                    //会自动选中。
                                    restordExpression.NewExID(action.ExID);

                                    restordExpression.ParentPanel.RefreshAutoNumbersOfBaseText();
                                }
                                else
                                {
                                    deletedExpression++;
                                }
                            }
                            else
                            {
                                Expressions.Expression ex = subPanel.BasePanel.Children[action.ExIndex] as Expressions.Expression;
                                if (ex != null)
                                {
                                    Expressions.Expression restordExpression =
                                        Commands.Command.InsertExpressionByXmlString(true,
                                        action.NewValue, ex);
                                    //会自动选中。
                                    restordExpression.NewExID(action.ExID);

                                    restordExpression.ParentPanel.RefreshAutoNumbersOfBaseText();
                                }
                                else
                                {
                                    deletedExpression++;
                                }
                            }

                            break;
                        }
                    case ActionType.Delete:
                        {
                            #region Delete
                            Expressions.Expression ex = editor.GetExpressionByExID(editor.RootPanel, action.ExID);
                            if (ex == null) return;

                            Expressions.SubPanel sPanel = ex.ParentPanel;
                            sPanel.XmlData.RemoveChild(ex.XmlData);
                            sPanel.BasePanel.Children.Remove(ex);

                            if (action.ExIndex > sPanel.BasePanel.Children.Count - 1)
                            {
                                //应选中最后一个
                                if (sPanel.BasePanel.Children.Count > 0)
                                {
                                    editor.SelectedExpression =
                                        sPanel.BasePanel.Children[sPanel.BasePanel.Children.Count - 1] as Expressions.Expression;
                                }
                            }
                            else if (action.ExIndex > 0)
                            {
                                editor.SelectedExpression = sPanel.BasePanel.Children[action.ExIndex - 1] as Expressions.Expression;
                            }
                            else if (action.ExIndex == 0)
                            {
                                if (sPanel.BasePanel.Children.Count > 0)
                                {
                                    editor.SelectedExpression = sPanel.BasePanel.Children[0] as Expressions.Expression;
                                }
                                else
                                {
                                    editor.SelectedExpression = sPanel;
                                }
                            }

                            sPanel.RefreshAutoNumbersOfBaseText();

                            break;
                            #endregion
                        }
                    case ActionType.CutOrDeleteTreeLeaf:
                        {
                            try
                            {
                                Expressions.Expression ex = editor.GetExpressionByExID(editor.RootPanel, action.ParentPanelOrExID);
                                if (ex == null || ex is Expressions.Tree == false) break;

                                Expressions.Tree pTree = ex as Expressions.Tree;

                                Expressions.Expression tmp = editor.GetExpressionByExID(pTree, action.ExID);
                                if (tmp == null || tmp is Expressions.LeafPanel == false) break;

                                Expressions.LeafPanel lPanel = tmp as Expressions.LeafPanel;

                                pTree.XmlData.RemoveChild(lPanel.XmlData);
                                pTree.BasePanel.Children.Remove(lPanel);
                                if (pTree.SubPanels.Contains(lPanel))
                                {
                                    pTree.SubPanels.Remove(lPanel);
                                }

                                pTree.RefreshLayout(true);
                                //注意，此处不必考虑相关索引。因为这里仅仅是一个“撤销”操作中的一小步。
                            }
                            catch (Exception ex)
                            {
                                Dialogs.LunarMsgBox.MsgBoxShow(
                                    Globals.appName,
                                    "重做“DeleteTreeLeaf”时出错。",
                                    "异常信息如下：\r\n" + ex.Message,
                                    ex.StackTrace, MessageBoxButton.OK, MessageBoxImage.Warning);
                            }
                            break;
                        }
                    case ActionType.InsertGridPanel:
                        {
                            Expressions.Expression tmpGrid = editor.GetExpressionByExID(editor.RootPanel, action.ParentPanelOrExID);
                            if (tmpGrid == null || tmpGrid is Expressions.Grid == false) break;

                            Expressions.Grid grid = tmpGrid as Expressions.Grid;

                            Expressions.GridPanel restordGridPanel = new Expressions.GridPanel(
                                grid.RootPanel, grid.ParentPanel, grid.Editor, grid);

                            if (grid.XmlData.LastChild.InsertXml(action.NewValue))
                            {
                                restordGridPanel.XmlData = grid.XmlData.LastChild;
                                restordGridPanel.NewExID(action.ExID);
                            }

                            grid.BaseGrid.Children.Add(restordGridPanel);
                            grid.SubPanels.Add(restordGridPanel);

                            System.Windows.Controls.Grid.SetColumn(restordGridPanel, restordGridPanel.GridX);
                            System.Windows.Controls.Grid.SetRow(restordGridPanel, restordGridPanel.GridY);

                            break;
                        }
                    case ActionType.InsertSameLevelLeaf:
                    case ActionType.InsertNextLevelLeaf:
                        {
                            Expressions.Expression ex = editor.GetExpressionByExID(editor.RootPanel, action.ParentPanelOrExID);
                            if (ex == null || ex is Expressions.Tree == false) break;

                            Expressions.Tree pTree = ex as Expressions.Tree;

                            Expressions.LeafPanel restoredLeaf = new LeafPanel(
                                pTree.RootPanel, pTree.ParentPanel, pTree.Editor, pTree);

                            if (pTree.XmlData.LastChild.InsertXml(action.NewValue))
                            {
                                restoredLeaf.XmlData = pTree.XmlData.LastChild;
                                restoredLeaf.NewExID(action.ExID);
                            }

                            pTree.BasePanel.Children.Add(restoredLeaf);
                            pTree.SubPanels.Add(restoredLeaf);

                            restoredLeaf.SizeChanged += new SizeChangedEventHandler(restoredLeaf_SizeChanged);

                            restoredLeaf.InvalidateArrange();
                            //restordLeaf.UpdateLayout();

                            pTree.RefreshLayout(true);
                            break;
                        }
                    case ActionType.MoveLeafHorizontal:
                        {
                            Expressions.Expression ex = editor.GetExpressionByExID(editor.RootPanel, action.ExID);
                            if (ex != null && ex is Expressions.Tree)
                            {
                                Expressions.Tree pTree = ex as Expressions.Tree;
                                pTree.RefreshLayout(true);
                            }
                            break;
                        }
                    case ActionType.DeleteGridPanel:
                        {
                            try
                            {
                                Expressions.Expression tmpgrid = editor.GetExpressionByExID(editor.RootPanel, action.ParentPanelOrExID);
                                if (tmpgrid == null || tmpgrid is Expressions.Grid == false) break;

                                Expressions.Grid grid = tmpgrid as Expressions.Grid;

                                Expressions.Expression tmp = editor.GetExpressionByExID(grid, action.ExID);
                                if (tmp == null || tmp is Expressions.GridPanel == false) break;

                                Expressions.GridPanel gPanel = tmp as Expressions.GridPanel;

                                grid.XmlData.RemoveChild(gPanel.XmlData);
                                grid.BaseGrid.Children.Remove(gPanel);
                                if (grid.SubPanels.Contains(gPanel))
                                {
                                    grid.SubPanels.Remove(gPanel);
                                }

                                gPanel.GridX = -1;
                                gPanel.GridY = -1;
                            }
                            catch (Exception ex)
                            {
                                Dialogs.LunarMsgBox.MsgBoxShow(
                                    Globals.appName,
                                    "重做“DeleteGridPanel”时出错。",
                                    "异常信息如下：\r\n" + ex.Message,
                                    ex.StackTrace, MessageBoxButton.OK, MessageBoxImage.Warning);
                            }
                            break;
                        }
                    case ActionType.MoveToNext:
                        {
                            Expressions.Expression curEx = editor.GetExpressionByExID(editor.RootPanel, action.ExID);
                            if (curEx == null) { return; }

                            Expressions.SubPanel parentPanel = curEx.ParentPanel;
                            int indexOfCurEx = parentPanel.BasePanel.Children.IndexOf(curEx);
                            if (indexOfCurEx > parentPanel.BasePanel.Children.Count - 2) return;//已在最后一位，无法再后移。

                            parentPanel.BasePanel.Children.Remove(curEx);
                            curEx.XmlData.MoveToNext();

                            int newIndex = indexOfCurEx + 1;
                            if (newIndex > parentPanel.BasePanel.Children.Count)
                            {
                                newIndex = parentPanel.BasePanel.Children.Count;
                            }

                            parentPanel.BasePanel.Children.Insert(newIndex, curEx);
                            break;
                        }
                    case ActionType.MoveToPreview:
                        {
                            Expressions.Expression curEx = editor.GetExpressionByExID(editor.RootPanel, action.ExID);
                            if (curEx == null) { return; }

                            Expressions.SubPanel parentPanel = curEx.ParentPanel;
                            int indexOfCurEx = parentPanel.BasePanel.Children.IndexOf(curEx);
                            if (indexOfCurEx < 1) return;//已在第一位，无法再前移。

                            parentPanel.BasePanel.Children.Remove(curEx);
                            curEx.XmlData.MoveToPrevious();

                            int newIndex = indexOfCurEx;
                            if (newIndex < 1) newIndex = 1;

                            parentPanel.BasePanel.Children.Insert(newIndex - 1, curEx);

                            break;
                        }
                    case ActionType.FontSizeChanging:
                        {
                            editor.ExFontSize = double.Parse(action.NewValue);
                            editor.ParentWindow.UpdateFontSizeSliderValue(editor.ExFontSize);
                            break;
                        }
                    case ActionType.DefaultExBackgroundChanging:
                        {
                            Brush bsh = ColorPicker.GetBrushByName(action.NewValue);
                            if (bsh != null)
                            {
                                editor.DefaultBackground = bsh;
                            }
                            else
                            {
                                //可能是图像。
                                string imgDataText = action.NewValue;
                                System.Windows.Media.Imaging.BitmapImage bmp = new System.Windows.Media.Imaging.BitmapImage();

                                if (imgDataText != null && imgDataText.Length > 0)
                                {
                                    byte[] b = Convert.FromBase64String(imgDataText);
                                    bmp.BeginInit();
                                    bmp.StreamSource = new MemoryStream(b);
                                    bmp.EndInit();

                                    ImageBrush iBsh = new ImageBrush(bmp) { Stretch = System.Windows.Media.Stretch.UniformToFill };
                                    iBsh.ViewportUnits = System.Windows.Media.BrushMappingMode.Absolute;
                                    iBsh.Viewport = new System.Windows.Rect(0, 0, iBsh.ImageSource.Width, iBsh.ImageSource.Height);

                                    XmlAttribute attrTileMode = editor.XmlDocument.DocumentElement.GetAttributeByName("TileMode");
                                    if (attrTileMode != null)
                                    {
                                        iBsh.TileMode = (TileMode)Enum.Parse(typeof(TileMode), attrTileMode.Value);
                                    }

                                    editor.RefreshDefaultBackgroundWithoutXml(iBsh);
                                    editor.RootPanel.XmlData.SetAttribute("DefaultBackground", action.NewValue);
                                }
                                else
                                {
                                    editor.RefreshDefaultBackgroundWithoutXml(Brushes.Black);
                                }
                            }

                            break;
                        }
                    case ActionType.TileMode:
                        {
                            ImageBrush iBsh = editor.DefaultBackground as ImageBrush;
                            if (iBsh != null && action.NewValue != null && action.NewValue.Length > 0)
                            {
                                iBsh.TileMode = (TileMode)Enum.Parse(typeof(TileMode), action.NewValue);
                                editor.XmlDocument.DocumentElement.SetAttribute("TileMode", action.NewValue);
                            }

                            break;
                        }
                    case ActionType.DefaultExForegroundChanging:
                        {
                            editor.DefaultForeground = ColorPicker.GetBrushByName(action.NewValue);
                            break;
                        }
                    case ActionType.ExSelectionAdornerBrushChanging:
                        {
                            editor.ExSelectionAdornerBrush = ColorPicker.GetBrushByName(action.NewValue);
                            break;
                        }
                    case ActionType.SubPanelSelectionAdornerBrushChanging:
                        {
                            editor.SubPanelSelectionAdornerBrush = ColorPicker.GetBrushByName(action.NewValue);
                            break;
                        }
                    case ActionType.DefaultHeaderText1ColorChanging:
                        {
                            editor.DefHeaderText1Brush = ColorPicker.GetBrushByName(action.NewValue); break;
                        }
                    case ActionType.DefaultHeaderText2ColorChanging:
                        {
                            editor.DefHeaderText2Brush = ColorPicker.GetBrushByName(action.NewValue); break;
                        }
                    case ActionType.DefaultHeaderText3ColorChanging:
                        {
                            editor.DefHeaderText3Brush = ColorPicker.GetBrushByName(action.NewValue); break;
                        }
                    case ActionType.DefaultHeaderText4ColorChanging:
                        {
                            editor.DefHeaderText4Brush = ColorPicker.GetBrushByName(action.NewValue); break;
                        }
                    case ActionType.AutoWrap:
                        {
                            editor.AutoWrap = bool.Parse(action.NewValue);
                            break;
                        }
                    case ActionType.MaxTextWidth:
                        {
                            editor.MaxTextWidth = double.Parse(action.NewValue);
                            break;
                        }
                    case ActionType.MaxWidthOfRootPanel:
                        {
                            editor.MaxWidthOfRootPanel = action.NewValue;
                            break;
                        }
                    case ActionType.PageHeaderLeft:
                        {
                            editor.PageHeaderLeft = action.NewValue; break;
                        }
                    case ActionType.PageHeaderMiddle:
                        {
                            editor.PageHeaderMiddle = action.NewValue; break;
                        }
                    case ActionType.PageHeaderRight:
                        {
                            editor.PageHeaderRight = action.NewValue; break;
                        }
                    case ActionType.PageSetting:
                        {
                            editor.PageSettingInfoSource = action.NewValue; break;
                        }
                }

                if (mi.EditorOffset != null)
                {
                    editor.BaseScrolledViewer.ScrollToHorizontalOffset(mi.EditorOffset.X);
                    editor.BaseScrolledViewer.ScrollToVerticalOffset(mi.EditorOffset.Y);
                }

                if (mi.NewSelectedExID != null)
                {
                    Expressions.Expression ex = editor.GetExpressionByExID(editor.RootPanel, mi.NewSelectedExID);
                    if (ex != null)
                    {
                        editor.SelectedExpression = ex;
                    }
                }
            }

            //point++;不能放在此处，而是方法头部。

            //if (deletedExpression >= mi.ModifiedPropertyAndValues.Count)
            //{
            //Redo();
            //}

            if (mi.AutoNumPanelID != null)
            {
                Expressions.SubPanel autoNumPanel = editor.GetExpressionByExID
                    (editor.RootPanel, mi.AutoNumPanelID) as Expressions.SubPanel;
                if (autoNumPanel != null)
                {
                    autoNumPanel.RefreshAutoNumbersOfBaseText();
                }
            }

            if (editor != null && editor.SelectedExpression != null &&
                editor.SelectedExpression.ParentPanel != null &&
                editor.SelectedExpression is Expressions.SubPanel == false)
            {
                editor.SelectedExpression.ParentPanel.RefreshHeaderTextCollapsed();
            }

            if (point == pointOfSaving)
            {
                Editor.IsModified = false;
            }
            else
            {
                Editor.IsModified = true;
            }
        }

        void restoredLeaf_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            Expressions.LeafPanel lp = sender as Expressions.LeafPanel;
            if (lp == null) return;

            Expressions.Tree pTree = lp.ParentExpression as Expressions.Tree;
            if (pTree == null) return;

            pTree.RefreshLayout();
        }

        public bool CanUndo
        {
            get
            {
                if (Point < 0 || Point > this.Count - 1) return false;
                if (this.Count <= 0) return false;
                return true;
            }
        }

        public void Undo()
        {
            if (CanUndo == false) return;

            ModifingItem mi = this[point] as ModifingItem;

            int deletedExpression = 0;

            //撤销应逆序！！！
            for (int i = mi.ModifiedPropertyAndValues.Count - 1; i >= 0; i--)
            {
                Action action = mi.ModifiedPropertyAndValues[i];
                switch (action.ActionType)
                {
                    case ActionType.Property:
                        {
                            Expressions.Expression ex = editor.GetExpressionByExID(editor.RootPanel, action.ExID);
                            if (ex != null)
                            {
                                ex.Undo(action);

                                //顶级标题的字号变化会影响自动编号。故应刷新自动编号。
                                if (action.Name == "FontSizeLevel" && ex.ParentPanel != null)
                                {
                                    ex.ParentPanel.RefreshAutoNumbersOfBaseText();
                                }
                            }
                            else
                            {
                                deletedExpression++;
                            }

                            break;
                        }
                    case ActionType.Insert:
                        {
                            #region Insert
                            Expressions.Expression ex = editor.GetExpressionByExID(editor.RootPanel, action.ExID);
                            if (ex != null)
                            {
                                Expressions.SubPanel parentPanel = ex.ParentPanel;

                                parentPanel.XmlData.RemoveChild(ex.XmlData);
                                parentPanel.BasePanel.Children.Remove(ex);

                                //这个公式是插入时的基准位置。
                                if (action.ExIndex >= 0)
                                {
                                    if (action.ExIndex == 0)
                                    {
                                        if (parentPanel.BasePanel.Children.Count >= 1)
                                        {
                                            editor.SelectedExpression = parentPanel.BasePanel.Children[0] as Expressions.Expression;
                                        }
                                        else
                                        {
                                            editor.SelectedExpression = parentPanel;
                                        }
                                    }
                                    else
                                    {
                                        if (action.ExIndex >= parentPanel.BasePanel.Children.Count - 1)
                                        {
                                            //如果要撤销插入的公式是所在子面板中最后一个公式。
                                            if (parentPanel.BasePanel.Children.Count > 0 && action.ExIndex - 1 >= 0)
                                            {
                                                editor.SelectedExpression = parentPanel.BasePanel.Children[action.ExIndex - 1] as Expressions.Expression;
                                            }
                                        }
                                        else
                                        {
                                            editor.SelectedExpression = parentPanel.BasePanel.Children[action.ExIndex] as Expressions.Expression;
                                        }
                                    }
                                }

                                parentPanel.RefreshAutoNumbersOfBaseText();
                            }
                            else
                            {
                                deletedExpression++;
                            }
                            break;
                            #endregion
                        }
                    case ActionType.Delete:
                        {
                            #region Delete
                            Expressions.Expression exPanel = editor.GetExpressionByExID(editor.RootPanel, action.ParentPanelOrExID);
                            if (exPanel == null || (exPanel is Expressions.Expression == false)) return;

                            Expressions.SubPanel subPanel = exPanel as Expressions.SubPanel;

                            if (action.ExIndex <= 0)
                            {
                                Expressions.Expression ex = subPanel.BasePanel.Children[0] as Expressions.Expression;
                                if (ex != null)
                                {
                                    Expressions.Expression restordExpression =
                                        Commands.Command.InsertExpressionByXmlString(true,
                                        action.OldValue, ex);
                                    //会自动选中。
                                    restordExpression.NewExID(action.ExID);
                                }
                                else
                                {
                                    deletedExpression++;
                                }
                            }
                            else
                            {
                                //以前一个为基准。
                                Expressions.Expression ex = subPanel.BasePanel.Children[action.ExIndex - 1] as Expressions.Expression;
                                if (ex != null)
                                {
                                    Expressions.Expression restordExpression =
                                        Commands.Command.InsertExpressionByXmlString(false,
                                        action.OldValue, ex);
                                    //会自动选中。
                                    restordExpression.NewExID(action.ExID);
                                }
                                else
                                {
                                    deletedExpression++;
                                }
                            }

                            subPanel.RefreshAutoNumbersOfBaseText();

                            break;
                            #endregion
                        }
                    case ActionType.CutOrDeleteTreeLeaf:
                        {
                            Expressions.Expression ex = Editor.GetExpressionByExID(editor.RootPanel, action.ParentPanelOrExID);
                            if (ex == null || ex is Expressions.Tree == false)
                            {
                                MessageBox.Show("根据传入Action的“父公式ID”找不到父树！",
                                    Globals.appName, MessageBoxButton.OK, MessageBoxImage.Warning);
                                break;
                            }

                            Expressions.Tree pTree = ex as Expressions.Tree;

                            Expressions.LeafPanel restoredLeaf = new LeafPanel(pTree.RootPanel, null,
                                Editor, pTree);

                            if (pTree.XmlData.LastChild.InsertXml(action.OldValue, true))
                            {
                                restoredLeaf.XmlData = pTree.XmlData.LastChild;
                                restoredLeaf.NewExID(action.ExID);
                            }

                            restoredLeaf.SizeChanged += new SizeChangedEventHandler(restoredLeaf_SizeChanged);

                            pTree.BasePanel.Children.Add(restoredLeaf);
                            pTree.SubPanels.Add(restoredLeaf);

                            restoredLeaf.InvalidateArrange();
                            //restoredLeaf.UpdateLayout();

                            pTree.RefreshLayout(true);
                            break;
                        }
                    case ActionType.InsertGridPanel:
                        {
                            try
                            {
                                Expressions.Expression tmpgrid = editor.GetExpressionByExID(editor.RootPanel, action.ParentPanelOrExID);
                                if (tmpgrid == null || tmpgrid is Expressions.Grid == false) break;

                                Expressions.Grid grid = tmpgrid as Expressions.Grid;

                                Expressions.Expression tmp = editor.GetExpressionByExID(grid, action.ExID);
                                if (tmp == null || tmp is Expressions.GridPanel == false) break;

                                Expressions.GridPanel gPanel = tmp as Expressions.GridPanel;

                                grid.XmlData.RemoveChild(gPanel.XmlData);
                                grid.BaseGrid.Children.Remove(gPanel);
                                if (grid.SubPanels.Contains(gPanel))
                                {
                                    grid.SubPanels.Remove(gPanel);
                                }

                                gPanel.GridX = -1;
                                gPanel.GridY = -1;
                            }
                            catch (Exception ex)
                            {
                                Dialogs.LunarMsgBox.MsgBoxShow(
                                    Globals.appName,
                                    "撤销“InsertGridPanel”时出错。",
                                    "异常信息如下：\r\n" + ex.Message,
                                    ex.StackTrace, MessageBoxButton.OK, MessageBoxImage.Warning);
                            }
                            break;
                        }
                    case ActionType.InsertSameLevelLeaf:
                    case ActionType.InsertNextLevelLeaf:
                        {
                            try
                            {
                                Expressions.Expression tmpTree = editor.GetExpressionByExID(editor.RootPanel, action.ParentPanelOrExID);
                                if (tmpTree == null || tmpTree is Expressions.Tree == false) break;

                                Expressions.Tree pTree = tmpTree as Expressions.Tree;

                                Expressions.Expression tmp = editor.GetExpressionByExID(pTree, action.ExID);
                                if (tmp == null || tmp is Expressions.LeafPanel == false) break;

                                Expressions.LeafPanel leaf = tmp as Expressions.LeafPanel;

                                pTree.XmlData.RemoveChild(leaf.XmlData);
                                pTree.BasePanel.Children.Remove(leaf);
                                if (pTree.SubPanels.Contains(leaf))
                                {
                                    pTree.SubPanels.Remove(leaf);
                                }

                                LeafPanel preLeaf = leaf.PreLevelLeaf;
                                if (preLeaf != null)
                                {
                                    List<LeafPanel> levelLeaves = preLeaf.NextLevelLeaves;
                                    if (levelLeaves != null && levelLeaves.Contains(leaf))
                                    {
                                        levelLeaves.Remove(leaf);
                                    }
                                }

                                pTree.RefreshLayout(true);
                            }
                            catch (Exception exception)
                            {
                                Dialogs.LunarMsgBox.MsgBoxShow(
                                    Globals.appName,
                                    "撤销“InsertLeaf”时出错：",
                                    "异常信息如下：\r\n" + exception.Message,
                                    exception.StackTrace, MessageBoxButton.OK, MessageBoxImage.Warning);
                            }
                            break;
                        }
                    case ActionType.DeleteGridPanel:
                        {
                            #region DeleteGridPanel
                            Expressions.Expression tmpGrid = editor.GetExpressionByExID(editor.RootPanel, action.ParentPanelOrExID);
                            if (tmpGrid == null || tmpGrid is Expressions.Grid == false) break;

                            Expressions.Grid grid = tmpGrid as Expressions.Grid;

                            Expressions.GridPanel restordGridPanel = new Expressions.GridPanel(
                                grid.RootPanel, grid.ParentPanel, grid.Editor, grid);

                            if (grid.XmlData.LastChild.InsertXml(action.OldValue))
                            {
                                restordGridPanel.XmlData = grid.XmlData.LastChild;
                                restordGridPanel.NewExID(action.ExID);
                            }

                            grid.BaseGrid.Children.Add(restordGridPanel);
                            grid.SubPanels.Add(restordGridPanel);

                            System.Windows.Controls.Grid.SetColumn(restordGridPanel, restordGridPanel.GridX);
                            System.Windows.Controls.Grid.SetRow(restordGridPanel, restordGridPanel.GridY);

                            break;
                            #endregion
                        }
                    case ActionType.MoveLeafHorizontal:
                        {
                            Expressions.Expression ex = editor.GetExpressionByExID(editor.RootPanel, action.ExID);
                            if (ex != null && ex is Expressions.Tree)
                            {
                                Expressions.Tree pTree = ex as Expressions.Tree;
                                pTree.RefreshLayout(true);
                            }
                            break;
                        }
                    case ActionType.MoveToNext:
                        {
                            #region MoveToNext
                            Expressions.Expression curEx = editor.GetExpressionByExID(editor.RootPanel, action.ExID);
                            if (curEx == null) { return; }

                            Expressions.SubPanel parentPanel = curEx.ParentPanel;
                            int indexOfCurEx = parentPanel.BasePanel.Children.IndexOf(curEx);
                            if (indexOfCurEx < 1) return;//已在第一位，无法再前移。

                            parentPanel.BasePanel.Children.Remove(curEx);
                            curEx.XmlData.MoveToPrevious();

                            int newIndex = indexOfCurEx;
                            if (newIndex < 1) newIndex = 1;

                            parentPanel.BasePanel.Children.Insert(newIndex - 1, curEx);

                            break;
                            #endregion
                        }
                    case ActionType.MoveToPreview:
                        {
                            #region MoveToPreview
                            Expressions.Expression curEx = editor.GetExpressionByExID(editor.RootPanel, action.ExID);
                            if (curEx == null) { return; }

                            Expressions.SubPanel parentPanel = curEx.ParentPanel;
                            int indexOfCurEx = parentPanel.BasePanel.Children.IndexOf(curEx);
                            if (indexOfCurEx > parentPanel.BasePanel.Children.Count - 2) return;//已在最后一位，无法再后移。

                            parentPanel.BasePanel.Children.Remove(curEx);
                            curEx.XmlData.MoveToNext();

                            int newIndex = indexOfCurEx + 1;
                            if (newIndex > parentPanel.BasePanel.Children.Count)
                            {
                                newIndex = parentPanel.BasePanel.Children.Count;
                            }

                            parentPanel.BasePanel.Children.Insert(newIndex, curEx);

                            break;
                            #endregion
                        }
                    case ActionType.FontSizeChanging:
                        {
                            editor.ExFontSize = double.Parse(action.OldValue);
                            editor.ParentWindow.UpdateFontSizeSliderValue(editor.ExFontSize);
                            break;
                        }
                    case ActionType.DefaultExBackgroundChanging:
                        {
                            Brush bsh = ColorPicker.GetBrushByName(action.OldValue);

                            if (bsh != null)
                            {
                                editor.DefaultBackground = bsh;
                            }
                            else
                            {
                                //可能是图像。
                                string imgDataText = action.OldValue;
                                System.Windows.Media.Imaging.BitmapImage bmp = new System.Windows.Media.Imaging.BitmapImage();

                                if (imgDataText != null && imgDataText.Length > 0)
                                {
                                    byte[] b = Convert.FromBase64String(imgDataText);
                                    bmp.BeginInit();
                                    bmp.StreamSource = new MemoryStream(b);
                                    bmp.EndInit();

                                    ImageBrush iBsh = new ImageBrush(bmp) { Stretch = System.Windows.Media.Stretch.UniformToFill };
                                    iBsh.ViewportUnits = System.Windows.Media.BrushMappingMode.Absolute;
                                    iBsh.Viewport = new System.Windows.Rect(0, 0, iBsh.ImageSource.Width, iBsh.ImageSource.Height);

                                    XmlAttribute attrTileMode = editor.XmlDocument.DocumentElement.GetAttributeByName("TileMode");
                                    if (attrTileMode != null)
                                    {
                                        iBsh.TileMode = (TileMode)Enum.Parse(typeof(TileMode), attrTileMode.Value);
                                    }

                                    editor.RefreshDefaultBackgroundWithoutXml(iBsh);
                                    editor.RootPanel.XmlData.SetAttribute("DefaultBackground", action.OldValue);
                                }
                                else
                                {
                                    editor.RefreshDefaultBackgroundWithoutXml(Brushes.Black);
                                }
                            }

                            break;
                        }
                    case ActionType.TileMode:
                        {
                            ImageBrush iBsh = editor.DefaultBackground as ImageBrush;
                            if (iBsh != null && action.OldValue != null && action.OldValue.Length > 0)
                            {
                                iBsh.TileMode = (TileMode)Enum.Parse(typeof(TileMode), action.OldValue);
                                editor.XmlDocument.DocumentElement.SetAttribute("TileMode", action.OldValue);
                            }

                            break;
                        }
                    case ActionType.DefaultExForegroundChanging:
                        {
                            editor.DefaultForeground = ColorPicker.GetBrushByName(action.OldValue);
                            break;
                        }
                    case ActionType.ExSelectionAdornerBrushChanging:
                        {
                            editor.ExSelectionAdornerBrush = ColorPicker.GetBrushByName(action.OldValue);
                            break;
                        }
                    case ActionType.SubPanelSelectionAdornerBrushChanging:
                        {
                            editor.SubPanelSelectionAdornerBrush = ColorPicker.GetBrushByName(action.OldValue);
                            break;
                        }
                    case ActionType.DefaultHeaderText1ColorChanging:
                        {
                            editor.DefHeaderText1Brush = ColorPicker.GetBrushByName(action.OldValue); break;
                        }
                    case ActionType.DefaultHeaderText2ColorChanging:
                        {
                            editor.DefHeaderText2Brush = ColorPicker.GetBrushByName(action.OldValue); break;
                        }
                    case ActionType.DefaultHeaderText3ColorChanging:
                        {
                            editor.DefHeaderText3Brush = ColorPicker.GetBrushByName(action.OldValue); break;
                        }
                    case ActionType.DefaultHeaderText4ColorChanging:
                        {
                            editor.DefHeaderText4Brush = ColorPicker.GetBrushByName(action.OldValue); break;
                        }
                    case ActionType.AutoWrap:
                        {
                            editor.AutoWrap = bool.Parse(action.OldValue);
                            break;
                        }
                    case ActionType.MaxTextWidth:
                        {
                            editor.MaxTextWidth = double.Parse(action.OldValue);
                            break;
                        }
                    case ActionType.MaxWidthOfRootPanel:
                        {
                            editor.MaxWidthOfRootPanel = action.OldValue;
                            break;
                        }
                    case ActionType.PageHeaderLeft:
                        {
                            editor.PageHeaderLeft = action.OldValue; break;
                        }
                    case ActionType.PageHeaderMiddle:
                        {
                            editor.PageHeaderMiddle = action.OldValue; break;
                        }
                    case ActionType.PageHeaderRight:
                        {
                            editor.PageHeaderRight = action.OldValue; break;
                        }
                    case ActionType.PageSetting:
                        {
                            editor.PageSettingInfoSource = action.OldValue; break;
                        }
                }
            }

            if (mi.EditorOffset != null)
            {
                editor.BaseScrolledViewer.ScrollToHorizontalOffset(mi.EditorOffset.X);
                editor.BaseScrolledViewer.ScrollToVerticalOffset(mi.EditorOffset.Y);
            }

            if (mi.OldSelectedExID != null)
            {
                Expressions.Expression ex = editor.GetExpressionByExID(editor.RootPanel, mi.OldSelectedExID);
                if (ex != null)
                {
                    editor.SelectedExpression = ex;
                    editor.SelectedExpression.RefreshSelectAdorner();
                }
            }

            //如果涉及到的所有公式都已经找不到了（被删除了）。则自动跳往下一次Undo。
            //if (deletedExpression >= mi.ModifiedPropertyAndValues.Count)
            //{
            point--;
            //    Undo();
            //}
            //else
            //{
            //    //Undo结束后才有必要令point减少1.——此时才有必要准备Undo前一次更改的值。
            //    point--;
            //}

            if (mi.AutoNumPanelID != null)
            {
                Expressions.SubPanel autoNumPanel = editor.GetExpressionByExID
                    (editor.RootPanel, mi.AutoNumPanelID) as Expressions.SubPanel;
                if (autoNumPanel != null)
                {
                    autoNumPanel.RefreshAutoNumbersOfBaseText();
                }
            }

            if (editor != null && editor.SelectedExpression != null &&
                editor.SelectedExpression.ParentPanel != null &&
                editor.SelectedExpression is Expressions.SubPanel == false)
            {
                editor.SelectedExpression.ParentPanel.RefreshHeaderTextCollapsed();
            }

            if (point == pointOfSaving)
            {
                Editor.IsModified = false;
            }
            else
            {
                Editor.IsModified = true;
            }
        }
    }
}
